/*
 *  liquidity/transaction.vala
 *
 *  Copyright (c) 2008 Patrick Walton <pcwalton@uchicago.edu>
 */

using GLib;
using Gee;
using Clutter;

namespace Liquidity {
    public class Transaction : Object {
        private static Transaction _default_transaction = null;
        private static Gee.ArrayList<Transaction> _transactions = null;

        /*
         *  Returns the default transaction for the current thread. If the
         *  default transaction doesn't exist yet, creates it.
         */
        private static Transaction get_default_transaction()
        {
            if (_default_transaction == null)
                _default_transaction = new Transaction(true);

            return _default_transaction;
        }

        private static Transaction get_current_transaction()
        {
            if (_transactions == null || ((Collection)_transactions).size == 0)
                return get_default_transaction();
            else
                return _transactions.get(((Collection)_transactions).size - 1);
        }

        public static void _add_update(Update update)
        {
            Transaction t = get_current_transaction();

            t.update_list.add(update);
            if (t.is_default)
                t._schedule_commit();
        }

        public Gee.ArrayList<Update> update_list;
        private bool is_default { get; set; }

        /* internal */ public Transaction(bool def)
        {
            is_default = def;
        }

        construct {
            update_list = new Gee.ArrayList<Update>();
        }

        public void _schedule_commit()
        {
            Idle.add(_commit_specific);
        }

        /*
         *  Internal function to commit a specific transaction. This is where
         *  the bulk of the implicit animation logic is.
         */
        public bool _commit_specific()
        {
            foreach (Update update in update_list) {
                /* TODO: allow user to customize duration */
                Timeline timeline = new Timeline(15, 60); 
                timeline.loop = false;

                /* TODO: custom alpha functions */
                Alpha alpha = new Alpha.full(timeline, Clutter.ramp_inc_func,
                        null, null); 

                Behaviour behavior = update.model.get_behavior_for_key_path(
                        update.key_path, alpha, timeline);
                behavior.apply(update.model.actor);

                Animation anim = new Animation(timeline, alpha, behavior);

                update.model._delete_implicit_animation(update.key_path);
                update.model._add_implicit_animation(update.key_path, anim);
            }

            update_list.clear();

            return false;
        }
    }
}

